/**
 * <pre>
 * Title: 		PortFactoryImpl.java
 * Author:		linriqing
 * Create:	 	2010-7-15 上午11:21:46
 * Copyright: 	Copyright (c) 2010
 * Company:		Shenzhen Helper
 * <pre>
 */
package com.hengpeng.itfin.port.impl;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import com.google.gson.Gson;
import com.hengpeng.common.configuration.ConfigProvider;
import com.hengpeng.common.configuration.ConfigProviderFactory;
import com.hengpeng.common.constant.Constant;
import com.hengpeng.common.persist.QueryParameter;
import com.hengpeng.common.persist.QueryResult;
import com.hengpeng.common.persist.entity.AbstractEntity;
import com.hengpeng.common.persist.query.DynamicQuery;
import com.hengpeng.common.util.MessageLoger;
import com.hengpeng.itfin.port.PortActiveFactory;
import com.hengpeng.itfinbase.message.ResponseMessage;
import com.hengpeng.itfinbase.message.TransMessage;

/**
 * <pre>
 * 远程接口工厂实现
 * </pre>
 * 
 * @author linriqing
 * @version 1.0, 2012-5-21
 */
@Component("portFactoryActiveImpl")
@Lazy
public class PortFactoryActiveImpl implements PortActiveFactory, ApplicationContextAware {
    private final static Log logger = LogFactory.getLog(PortFactoryActiveImpl.class);

    private static HttpHeaders httpHeaders = null;

    private final static ConfigProvider<String> cp = ConfigProviderFactory
            .getInstance(Constant.HP_COMMON_PROPERTIES_FILEPATH);

    public static HttpHeaders createBasicAuthHeaders(String userName, String password) {
        if (httpHeaders == null) {
            httpHeaders = new HttpHeaders();
            // Authorization
            String userPassword = userName + ":" + password;
            String encoding = new String(org.apache.commons.codec.binary.Base64.encodeBase64(userPassword.getBytes()),
                    Charset.forName("UTF-8"));
            httpHeaders.set("Authorization", "Basic " + encoding);

            // Accept
            List<MediaType> mediaTypes = new ArrayList<MediaType>();
            mediaTypes.add(MediaType.APPLICATION_XML);
            mediaTypes.add(MediaType.APPLICATION_JSON);
            httpHeaders.setAccept(mediaTypes);

            httpHeaders.set("Accept-Charset", "UTF-8");
        }
        return httpHeaders;
    }

    String DigestAuth_ClientId = "clientbasic";

    String DigestAuth_ClientPwd = "clientbasic4happycp";

    String DigestAuth_Key = "acegi";

    String DigestAuth_RealName = "Contacts Realm via Digest Authentication";

    private RestTemplate restTemplate;

    public <T> T doPostTrans(String transName, Class<T> returnType, Object parameter, Object... pathValue) {
        String url = cp.getConfigByPrimaryKey("active.service.url") + "/RemoteService/" + transName;
        HttpEntity<Object> entity = new HttpEntity<Object>(parameter, createBasicAuthHeaders(DigestAuth_ClientId,
                DigestAuth_ClientPwd));
        return (T) restTemplate.postForEntity(url, entity, returnType, pathValue).getBody();
    }

    @Override
    public <T extends AbstractEntity> QueryResult<T> remoteQuery(DynamicQuery query, Class<T> clz) {
        QueryParameter<T> qp = new QueryParameter<T>();
        qp.setCustomQuery(query);
        qp.setType(clz);
        return this.remoteQuery(qp);
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T extends AbstractEntity> QueryResult<T> remoteQuery(QueryParameter<T> queryParameters) {
        QueryResult<T> doPostTrans = this.doPostTrans("remoteQuery", QueryResult.class, queryParameters);
        if (!doPostTrans.getIsSuccess()) {
            logger.error("远程查询请求处理错误, Query{" + queryParameters.getCustomQuery().getSqlResult().getSql()
                    + "}, Parameter{" + queryParameters.getCustomQuery().getSqlResult().getParamsList() + "}");
        }
        return doPostTrans;
    }

    @Override
    public ResponseMessage remoteTrans(TransMessage transMessage) {
        Gson gson = new Gson();

        logger.info("远程交易请求,【transType=" + transMessage.getTransType() + "】,请求参数:{" + gson.toJson(transMessage) + "}");
        ResponseMessage doPostTrans = this.doPostTrans("remoteTrans", ResponseMessage.class, transMessage);
        logger.info("远程交易请求,【transType=" + transMessage.getTransType() + "】,响应信息:{" + gson.toJson(doPostTrans) + "}");
        MessageLoger.print(this.getClass(),
                "远程交易请求{" + gson.toJson(transMessage) + "},响应信息{" + gson.toJson(doPostTrans) + "}");
        return doPostTrans;
    }

    public <T extends ResponseMessage> T remoteTrans(TransMessage transMessage, Class<T> clz) {
        return clz.cast(remoteTrans(transMessage));
    }

    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        restTemplate = context.getBean(RestTemplate.class);
        DigestAuth_ClientId = cp.getConfigByPrimaryKey("DigestAuth_ClientId");
        DigestAuth_ClientPwd = cp.getConfigByPrimaryKey("DigestAuth_ClientPwd");
        DigestAuth_Key = cp.getConfigByPrimaryKey("DigestAuth_Key");
        DigestAuth_RealName = cp.getConfigByPrimaryKey("DigestAuth_RealName");
    }
}
